//
// Created by liwenjie on 2025/4/28.
//


#pragma once

#include <spdlog/spdlog.h>
#include <spdlog/common.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/sinks/rotating_file_sink.h>
#include <spdlog/sinks/daily_file_sink.h>
#include <spdlog/details/registry.h>
#include <spdlog/async_logger.h>
#include <spdlog/async.h>

#include <nlohmann/json.hpp>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <unordered_map>

using namespace spdlog;

namespace logger {
    class LogConfig {
    public:
        // 从JSON文件加载配置
        static void from_file(const std::string& file_path) {
            try {
                std::ifstream file(file_path);
                if (!file.is_open()) {
                    throw spdlog::spdlog_ex("无法打开配置文件: " + file_path);
                }

                nlohmann::json config;
                file >> config;

                // 应用配置
                apply_config(config);
            }
            catch (const nlohmann::json::exception& e) {
                throw spdlog::spdlog_ex(std::string("JSON解析错误: ") + e.what());
            }
        }

        // 从JSON字符串加载配置
        static void from_string(const std::string& json_str) {
            try {
                auto config = nlohmann::json::parse(json_str);

                // 应用配置
                apply_config(config);
            }
            catch (const nlohmann::json::exception& e) {
                throw spdlog::spdlog_ex(std::string("JSON解析错误: ") + e.what());
            }
        }

    private:
        // 应用JSON配置
        static void apply_config(const nlohmann::json& config) {
            // 存储创建的sink，以便后续引用
            std::unordered_map<std::string, std::shared_ptr<sinks::sink>> sinks_map;

            // 1. 应用全局配置
            if (config.contains("global")) {
                apply_global_config(config["global"]);
            }

            // 2. 创建和配置sinks
            if (config.contains("sinks") && config["sinks"].is_array()) {
                for (const auto& sink_config : config["sinks"]) {
                    if (sink_config.contains("name") && sink_config.contains("type")) {
                        std::string name = sink_config["name"];
                        auto sink = create_sink(sink_config);
                        if (sink) {
                            sinks_map[name] = sink;
                        }
                    }
                }
            }

            // 3. 创建和配置loggers
            if (config.contains("loggers") && config["loggers"].is_array()) {
                for (const auto& logger_config : config["loggers"]) {
                    if (logger_config.contains("name")) {
                        create_logger(logger_config, sinks_map);
                    }
                }
            }
        }

        // 应用全局配置
        static void apply_global_config(const nlohmann::json& global_config) {
            // 设置全局日志级别
            if (global_config.contains("level")) {
                std::string level_str = global_config["level"];
                auto level = level::from_str(level_str);
                spdlog::set_level(level);
            }

            // 设置全局格式
            if (global_config.contains("pattern")) {
                std::string pattern = global_config["pattern"];
                spdlog::set_pattern(pattern);
            }

            // 设置刷新级别
            if (global_config.contains("flush_on")) {
                std::string flush_on_str = global_config["flush_on"];
                auto flush_on = level::from_str(flush_on_str);
                spdlog::flush_on(flush_on);
            }

            // 设置异步模式
            if (global_config.contains("async")) {
                auto async_config = global_config["async"];
                size_t queue_size = async_config.value("queue_size", 8192);
                size_t thread_count = async_config.value("thread_count", 1);
                spdlog::init_thread_pool(queue_size, thread_count);
            }

            // 设置错误处理
            if (global_config.contains("error_handler") && global_config["error_handler"] == "default") {
                spdlog::set_error_handler([](const std::string& msg) {
                    std::cerr << "spdlog错误: " << msg << std::endl;
                });
            }
        }

        // 创建sink
        static std::shared_ptr<sinks::sink> create_sink(const nlohmann::json& sink_config) {
            std::string type = sink_config["type"];
            std::shared_ptr<sinks::sink> sink;

            // 根据类型创建不同的sink
            if (type == "console") {
                bool stdout_sink = sink_config.value("stdout", true);
                if (stdout_sink) {
                    sink = std::make_shared<sinks::stdout_color_sink_mt>();
                } else {
                    sink = std::make_shared<sinks::stderr_color_sink_mt>();
                }
            }
            else if (type == "file") {
                std::string filename = sink_config["filename"];
                bool truncate = sink_config.value("truncate", false);
                sink = std::make_shared<sinks::basic_file_sink_mt>(filename, truncate);
            }
            else if (type == "rotating_file") {
                std::string filename = sink_config["filename"];
                size_t max_size = sink_config.value("max_size", 1048576);
                size_t max_files = sink_config.value("max_files", 5);
                sink = std::make_shared<sinks::rotating_file_sink_mt>(filename, max_size, max_files);
            }
            else if (type == "daily_file") {
                std::string filename = sink_config["filename"];
                int hour = sink_config.value("hour", 0);
                int minute = sink_config.value("minute", 0);
                sink = std::make_shared<sinks::daily_file_sink_mt>(filename, hour, minute);
            }

            // 配置sink
            if (sink) {
                // 设置级别
                if (sink_config.contains("level")) {
                    std::string level_str = sink_config["level"];
                    auto level = level::from_str(level_str);
                    sink->set_level(level);
                }

                // 设置格式
                if (sink_config.contains("pattern")) {
                    std::string pattern = sink_config["pattern"];
                    sink->set_pattern(pattern);
                }
            }

            return sink;
        }

        // 创建logger
        static void create_logger(const nlohmann::json& logger_config,
                                  const std::unordered_map<std::string, std::shared_ptr<sinks::sink>>& sinks_map) {
            std::string name = logger_config["name"];

            // 收集sinks
            std::vector<spdlog::sink_ptr> sinks;
            if (logger_config.contains("sinks") && logger_config["sinks"].is_array()) {
                for (const auto& sink_name : logger_config["sinks"]) {
                    std::string sink_name_str = sink_name;
                    auto it = sinks_map.find(sink_name_str);
                    if (it != sinks_map.end()) {
                        sinks.push_back(it->second);
                    }
                }
            }

            // 创建logger
            std::shared_ptr<spdlog::logger> logger;
            if (logger_config.contains("async") && logger_config["async"].get<bool>()) {
                // 异步logger
                logger = std::make_shared<spdlog::async_logger>(name, sinks.begin(), sinks.end(),
                                                                spdlog::thread_pool(), spdlog::async_overflow_policy::block);
            } else {
                // 同步logger
                logger = std::make_shared<spdlog::logger>(name, sinks.begin(), sinks.end());
            }

            // 配置logger
            if (logger) {
                // 设置级别
                if (logger_config.contains("level")) {
                    std::string level_str = logger_config["level"];
                    auto level = level::from_str(level_str);
                    logger->set_level(level);
                }

                // 设置格式
                if (logger_config.contains("pattern")) {
                    std::string pattern = logger_config["pattern"];
                    logger->set_pattern(pattern);
                }

                // 注册logger
                spdlog::register_logger(logger);

                // 设置为默认logger
                if (logger_config.contains("default") && logger_config["default"].get<bool>()) {
                    spdlog::set_default_logger(logger);
                }
            }
        }
    };
}

